﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Globalization;
using System.Diagnostics;


namespace Engine.Dtd.Schema {
    /// <summary>
    /// Represents the declarations of element types and their attributes.
    /// </summary>
    [DebuggerDisplay("{Name}")]
    public sealed class DElementDeclaration {
        internal DElementDeclaration(DContentModel contentModel) {
            Guard.ArgumentNotNull(contentModel, "contentModel");
            Attributes = DAttributeDeclaration.EmptySequence;
            ContentModel = contentModel;
            }

        /// <summary>
        /// Gets the element name.
        /// </summary>
        public DName Name { get; internal set; }
        /// <summary>
        /// Gets or sets the value indicating that the start tag can be omitted.
        /// </summary>
        public bool StartTagOptional { get; set; }
        /// <summary>
        /// Gets or sets the value indicating that the end tag can be omitted.
        /// </summary>
        public bool EndTagOptional { get; set; }
        /// <summary>
        /// Gets the content model for this element.
        /// </summary>
        public DContentModel ContentModel { get; private set; }
        /// <summary>
        /// Gets a collection of attributes for this element.
        /// </summary>
        public IEnumerable<DAttribute> Attributes { get; internal set; }
        /// <summary>
        /// Gets a value indicating whether this declaration has at least one attribute.
        /// </summary>
        /// <returns>true if this declaration has at least one attribute; otherwise false.</returns>
        public bool HasAttributes {
            get { return Attributes != DAttributeDeclaration.EmptySequence; }
            }

        internal DElementType ElementType { get; set; }

        /// <summary>
        /// Parse the content type for the content model.
        /// </summary>
        /// <param name="value">The text specified the permissible declared child content.</param>
        /// <returns>A DContentModelType instance.</returns>
        /// <exception cref="ArgumentNullException">Argument Null Exception. If value is null.</exception>
        /// <exception cref="DtdException">DtdException</exception>
        public static DContentModelType ParseContentModelType(string value) {
            Guard.ArgumentNotNull(value, "value");
            // TODO: Validate that this can never combine with nested groups?
            switch (value) {
                case "EMPTY":
                    return DContentModelType.Empty;
                case "RCDATA":
                    return DContentModelType.RCData;
                case "CDATA":
                    return DContentModelType.CData;
                default:
                    throw new DtdException(String.Format(CultureInfo.CurrentUICulture, "The specified content model type '{0}' is not supported.", value));
                }
            }
        }
    }
